package net.sudot.flow.utils;

import groovy.lang.Binding;
import groovy.lang.Closure;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import groovy.lang.GroovyShell;
import groovy.util.GroovyScriptEngine;

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.net.URI;
import java.util.Map;

/**
 * Groovy 脚本执行工具
 *
 * @author tangjialin on 2020/2/18.
 */
public abstract class GroovyExecuteUtils {

    public static Object execute(String[] baseDirs, String scriptName, Map<Object, Object> variables) throws Exception {
        GroovyScriptEngine scriptEngine = new GroovyScriptEngine(baseDirs);
        return scriptEngine.run(scriptName, new Binding(variables));
    }

    public static Object execute(String baseDir, String scriptName, Map<Object, Object> variables) throws Exception {
        return execute(new String[]{baseDir}, scriptName, variables);
    }

    public static Object execute(String scriptText, Map<Object, Object> variables) throws Exception {
        GroovyShell shell = new GroovyShell(new Binding(variables));
        return shell.evaluate(scriptText);
    }

    public static Object execute(File scriptText, Map<Object, Object> variables) throws Exception {
        GroovyShell shell = new GroovyShell(new Binding(variables));
        return shell.evaluate(scriptText);
    }

    public static Object execute(Reader scriptText, Map<Object, Object> variables) throws Exception {
        GroovyShell shell = new GroovyShell(new Binding(variables));
        return shell.evaluate(scriptText);
    }

    public static Object execute(URI scriptText, Map<Object, Object> variables) throws Exception {
        GroovyShell shell = new GroovyShell(new Binding(variables));
        return shell.evaluate(scriptText);
    }

    /**
     * 加载Groovy类并创建实例
     */
    public static GroovyObject loadAndCreateGroovyObject(File sourceFile) {
        try {
            return (GroovyObject) new GroovyClassLoader().parseClass(sourceFile).newInstance();
        } catch (InstantiationException | IOException | IllegalAccessException e) {
            throw new IllegalArgumentException("", e);
        }
    }

    /**
     * 用闭包配置 Object
     *
     * @param closure  设置的闭包
     * @param delegate 设置的对象
     */
    public static void configureObjectWithClosure(Closure<?> closure, Object delegate) {
        Closure<?> c = (Closure<?>) closure.clone();
        c.setResolveStrategy(Closure.DELEGATE_FIRST);
        c.setDelegate(delegate);
        c.call();
    }
}
